
#include "stdafx.h"

#include "PropertiesWnd.h"
#include "Resource.h"
#include "MainFrm.h"
#include "RayTracer.h"
#include "Basis/Vector3.h"
#include "Camera/Camera.h"
#include "Render/Renderer.h"

#include <string>
using namespace std;

#include "RayTracerView.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

/////////////////////////////////////////////////////////////////////////////
// CResourceViewBar

CPropertiesWnd::CPropertiesWnd()
{
}

CPropertiesWnd::~CPropertiesWnd()
{
}

BEGIN_MESSAGE_MAP(CPropertiesWnd, CDockablePane)
	ON_WM_CREATE()
	ON_WM_SIZE()
	ON_COMMAND(ID_EXPAND_ALL, OnExpandAllProperties)
	ON_UPDATE_COMMAND_UI(ID_EXPAND_ALL, OnUpdateExpandAllProperties)
	ON_COMMAND(ID_SORTPROPERTIES, OnSortProperties)
	ON_UPDATE_COMMAND_UI(ID_SORTPROPERTIES, OnUpdateSortProperties)
// 	ON_COMMAND(ID_PROPERTIES1, OnProperties1)
// 	ON_UPDATE_COMMAND_UI(ID_PROPERTIES1, OnUpdateProperties1)
// 	ON_COMMAND(ID_PROPERTIES2, OnProperties2)
// 	ON_UPDATE_COMMAND_UI(ID_PROPERTIES2, OnUpdateProperties2)
	ON_WM_SETFOCUS()
	ON_WM_SETTINGCHANGE()
	ON_REGISTERED_MESSAGE(AFX_WM_PROPERTY_CHANGED, OnPropertyChanged)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CResourceViewBar message handlers

void CPropertiesWnd::AdjustLayout()
{
	if (GetSafeHwnd() == NULL)
	{
		return;
	}

	CRect rectClient;
	GetClientRect(rectClient);

	int cyTlb = m_wndToolBar.CalcFixedLayout(FALSE, TRUE).cy;
	m_wndToolBar.SetWindowPos(NULL, rectClient.left, rectClient.top, rectClient.Width(), cyTlb, SWP_NOACTIVATE | SWP_NOZORDER);
	m_wndPropList.SetWindowPos(NULL, rectClient.left, rectClient.top + cyTlb, rectClient.Width(), rectClient.Height() - cyTlb, SWP_NOACTIVATE | SWP_NOZORDER);

// 	CRect rectClient,rectCombo;
// 	GetClientRect(rectClient);
// 
// 	m_wndObjectCombo.GetWindowRect(&rectCombo);
// 
// 	int cyCmb = rectCombo.Size().cy;
// 	int cyTlb = m_wndToolBar.CalcFixedLayout(FALSE, TRUE).cy;
// 
// 	m_wndObjectCombo.SetWindowPos(NULL, rectClient.left, rectClient.top, rectClient.Width(), 200, SWP_NOACTIVATE | SWP_NOZORDER);
// 	m_wndToolBar.SetWindowPos(NULL, rectClient.left, rectClient.top + cyCmb, rectClient.Width(), cyTlb, SWP_NOACTIVATE | SWP_NOZORDER);
// 	m_wndPropList.SetWindowPos(NULL, rectClient.left, rectClient.top + cyCmb + cyTlb, rectClient.Width(), rectClient.Height() -(cyCmb+cyTlb), SWP_NOACTIVATE | SWP_NOZORDER);
}

int CPropertiesWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CDockablePane::OnCreate(lpCreateStruct) == -1)
		return -1;

	CRect rectDummy;
	rectDummy.SetRectEmpty();

	// Create combo:
	const DWORD dwViewStyle = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_BORDER | CBS_SORT | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;

// 	if (!m_wndObjectCombo.Create(dwViewStyle, rectDummy, this, 1))
// 	{
// 		TRACE0("Failed to create Properties Combo \n");
// 		return -1;      // fail to create
// 	}
// 
// 	m_wndObjectCombo.AddString(_T("Application"));
// 	m_wndObjectCombo.AddString(_T("Properties Window"));
// 	m_wndObjectCombo.SetCurSel(0);

	if (!m_wndPropList.Create(WS_VISIBLE | WS_CHILD, rectDummy, this, 2))
	{
		TRACE0("Failed to create Properties Grid \n");
		return -1;      // fail to create
	}

	InitPropList();

	m_wndToolBar.Create(this, AFX_DEFAULT_TOOLBAR_STYLE, IDR_PROPERTIES);
	m_wndToolBar.LoadToolBar(IDR_PROPERTIES, 0, 0, TRUE /* Is locked */);
	m_wndToolBar.CleanUpLockedImages();
	m_wndToolBar.LoadBitmap(theApp.m_bHiColorIcons ? IDB_PROPERTIES_HC : IDR_PROPERTIES, 0, 0, TRUE /* Locked */);

	m_wndToolBar.SetPaneStyle(m_wndToolBar.GetPaneStyle() | CBRS_TOOLTIPS | CBRS_FLYBY);
	m_wndToolBar.SetPaneStyle(m_wndToolBar.GetPaneStyle() & ~(CBRS_GRIPPER | CBRS_SIZE_DYNAMIC | CBRS_BORDER_TOP | CBRS_BORDER_BOTTOM | CBRS_BORDER_LEFT | CBRS_BORDER_RIGHT));
	m_wndToolBar.SetOwner(this);

	// All commands will be routed via this control , not via the parent frame:
	m_wndToolBar.SetRouteCommandsViaFrame(FALSE);

	AdjustLayout();
	return 0;
}

void CPropertiesWnd::OnSize(UINT nType, int cx, int cy)
{
	CDockablePane::OnSize(nType, cx, cy);
	AdjustLayout();
}

void CPropertiesWnd::OnExpandAllProperties()
{
	m_wndPropList.ExpandAll();
}

void CPropertiesWnd::OnUpdateExpandAllProperties(CCmdUI* /* pCmdUI */)
{
}

void CPropertiesWnd::OnSortProperties()
{
	m_wndPropList.SetAlphabeticMode(!m_wndPropList.IsAlphabeticMode());
}

void CPropertiesWnd::OnUpdateSortProperties(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(m_wndPropList.IsAlphabeticMode());
}

// void CPropertiesWnd::OnProperties1()
// {
// 	// TODO: Add your command handler code here
// }
// 
// void CPropertiesWnd::OnUpdateProperties1(CCmdUI* /*pCmdUI*/)
// {
// 	// TODO: Add your command update UI handler code here
// }
// 
// void CPropertiesWnd::OnProperties2()
// {
// 	// TODO: Add your command handler code here
// }
// 
// void CPropertiesWnd::OnUpdateProperties2(CCmdUI* /*pCmdUI*/)
// {
// 	// TODO: Add your command update UI handler code here
// }

void CPropertiesWnd::InitPropList()
{
	SetPropListFont();

	m_wndPropList.EnableHeaderCtrl(FALSE);
	m_wndPropList.EnableDescriptionArea();
	m_wndPropList.SetVSDotNetLook();
	m_wndPropList.MarkModifiedProperties();

	CString caption;
	
	caption.LoadStringW(PROPERTY_CENTER);
	CMFCPropertyGridProperty* pCenter = new CMFCPropertyGridProperty(caption);
		
		caption.LoadStringW(PROPERTY_CENTER_X);
		CMFCPropertyGridProperty* pProp = new CMFCPropertyGridProperty(caption, (_variant_t)0.0f, _T("x index of the camera"));
		pCenter->AddSubItem(pProp);
		
		caption.LoadStringW(PROPERTY_CENTER_Y);
		pProp = new CMFCPropertyGridProperty(caption, (_variant_t)0.0f, _T("y index of the camera"));
		pCenter->AddSubItem(pProp);

		caption.LoadStringW(PROPERTY_CENTER_Z);
		pProp = new CMFCPropertyGridProperty(caption, (_variant_t)0.0f, _T("z index of the camera"));
		pCenter->AddSubItem(pProp);

	m_wndPropList.AddProperty(pCenter);

	caption.LoadStringW(PROPERTY_GAZE);
	CMFCPropertyGridProperty* pGaze = new CMFCPropertyGridProperty(caption);

		caption.LoadStringW(PROPERTY_GAZE_X);
		pProp = new CMFCPropertyGridProperty(caption, (_variant_t)0.0f, _T("x index of the gaze direction"));
		pGaze->AddSubItem(pProp);

		caption.LoadStringW(PROPERTY_GAZE_Y);
		pProp = new CMFCPropertyGridProperty(caption, (_variant_t)0.0f, _T("y index of the gaze direction"));
		pGaze->AddSubItem(pProp);

		caption.LoadStringW(PROPERTY_GAZE_Z);
		pProp = new CMFCPropertyGridProperty(caption, (_variant_t)-1.0f, _T("z index of the gaze direction"));
		pGaze->AddSubItem(pProp);

	m_wndPropList.AddProperty(pGaze);

	caption.LoadStringW(PROPERTY_VUP);
	CMFCPropertyGridProperty* pVUp = new CMFCPropertyGridProperty(caption);

		caption.LoadStringW(PROPERTY_VUP_X);
		pProp = new CMFCPropertyGridProperty(caption, (_variant_t)0.0f, _T("x index of the up direction"));
		pVUp->AddSubItem(pProp);

		caption.LoadStringW(PROPERTY_VUP_Y);
		pProp = new CMFCPropertyGridProperty(caption, (_variant_t)1.0f, _T("y index of the up direction"));
		pVUp->AddSubItem(pProp);

		caption.LoadStringW(PROPERTY_VUP_Z);
		pProp = new CMFCPropertyGridProperty(caption, (_variant_t)0.0f, _T("z index of the up direction"));
		pVUp->AddSubItem(pProp);

	m_wndPropList.AddProperty(pVUp);
	
	caption.LoadStringW(PROPERTY_DISTANCE);
	CMFCPropertyGridProperty* pDistance = new CMFCPropertyGridProperty(caption, (_variant_t)900.0f,
		_T("the distance betweern the origin of the camera and the image plane"));
	m_wndPropList.AddProperty(pDistance);

	caption.LoadStringW(PROPERTY_APERTURE);
	CMFCPropertyGridProperty* pAperture = new CMFCPropertyGridProperty(caption, (_variant_t)161.0f, 
		_T("the diameter of the aperture"));
	m_wndPropList.AddProperty(pAperture);

	caption.LoadStringW(PROPERTY_TMIN);
	CMFCPropertyGridProperty* pTime = new CMFCPropertyGridProperty(caption, (_variant_t)0.0f, _T("exposure starts"));
	m_wndPropList.AddProperty(pTime);

	caption.LoadStringW(PROPERTY_TMAX);
	pTime = new CMFCPropertyGridProperty(caption, (_variant_t)1.0f, _T("exposure ends"));
	m_wndPropList.AddProperty(pTime);

}

void CPropertiesWnd::OnSetFocus(CWnd* pOldWnd)
{
	CDockablePane::OnSetFocus(pOldWnd);
	m_wndPropList.SetFocus();
}

void CPropertiesWnd::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
{
	CDockablePane::OnSettingChange(uFlags, lpszSection);
	SetPropListFont();
}

void CPropertiesWnd::SetPropListFont()
{
	::DeleteObject(m_fntPropList.Detach());

	LOGFONT lf;
	afxGlobalData.fontRegular.GetLogFont(&lf);

	NONCLIENTMETRICS info;
	info.cbSize = sizeof(info);

	afxGlobalData.GetNonClientMetrics(info);

	lf.lfHeight = info.lfMenuFont.lfHeight;
	lf.lfWeight = info.lfMenuFont.lfWeight;
	lf.lfItalic = info.lfMenuFont.lfItalic;

	m_fntPropList.CreateFontIndirect(&lf);

	m_wndPropList.SetFont(&m_fntPropList);
//	m_wndObjectCombo.SetFont(&m_fntPropList);
}

LRESULT CPropertiesWnd::OnPropertyChanged(WPARAM, LPARAM lParam)
{
	CMFCPropertyGridProperty* pProp = (CMFCPropertyGridProperty*)lParam;
	CString s = pProp->GetName();
	COleVariant var = pProp->GetValue();
	CMainFrame* pFrame = (CMainFrame *)AfxGetMainWnd();
	CRayTracerView* pView = (CRayTracerView *)(pFrame->GetActiveView());

	CString caption;
	Vector3 origin;
	
	Camera* pCamera = pView->getRenderer()->getCamera();
	if (caption.LoadStringW(PROPERTY_CENTER_X) && !s.Compare(caption))
	{
		origin = pCamera->getCenter();
		origin.setX(var.fltVal);
		pCamera->setCenter(origin);
	}
	else if (caption.LoadStringW(PROPERTY_CENTER_Y) && !s.Compare(caption))
	{
		origin = pCamera->getCenter();
		origin.setY(var.fltVal);
		pCamera->setCenter(origin);
	}
	else if (caption.LoadStringW(PROPERTY_CENTER_Z) && !s.Compare(caption))
	{
		origin = pCamera->getCenter();
		origin.setZ(var.fltVal);
		pCamera->setCenter(origin);
	}
	else if (caption.LoadStringW(PROPERTY_GAZE_X) && !s.Compare(caption))
	{
		origin = pCamera->getGaze();
		origin.setX(var.fltVal);
		pCamera->setGaze(origin);
	}
	else if (caption.LoadStringW(PROPERTY_GAZE_Y) && !s.Compare(caption))
	{
		origin = pCamera->getGaze();
		origin.setY(var.fltVal);
		pCamera->setGaze(origin);
	}
	else if (caption.LoadStringW(PROPERTY_GAZE_Z) && !s.Compare(caption))
	{
		origin = pCamera->getGaze();
		origin.setZ(var.fltVal);
		pCamera->setGaze(origin);
	}
	else if (caption.LoadStringW(PROPERTY_VUP_X) && !s.Compare(caption))
	{
		origin = pCamera->getVUp();
		origin.setX(var.fltVal);
		pCamera->setVUp(origin);
	}
	else if (caption.LoadStringW(PROPERTY_VUP_Y) && !s.Compare(caption))
	{
		origin = pCamera->getVUp();
		origin.setY(var.fltVal);
		pCamera->setVUp(origin);
	}
	else if (caption.LoadStringW(PROPERTY_VUP_Z) && !s.Compare(caption))
	{
		origin = pCamera->getVUp();
		origin.setZ(var.fltVal);
		pCamera->setVUp(origin);
	}
	else if (caption.LoadStringW(PROPERTY_DISTANCE) && !s.Compare(caption))
	{
		pCamera->setDistance(var.fltVal);
	}
	else if (caption.LoadStringW(PROPERTY_APERTURE) && !s.Compare(caption))
	{
		pCamera->setAperture(var.fltVal);
	}
	else if (caption.LoadString(PROPERTY_TMIN) && !s.Compare(caption))
	{
		pCamera->setTmin(var.fltVal);
	}
	else if (caption.LoadStringW(PROPERTY_TMAX) && !s.Compare(caption))
	{
		pCamera->setTmax(var.fltVal);
	}
	return 0;
}